import { TinyColor } from '@ctrl/tinycolor';
/**
 * 验证是否为 16 进制颜色的正则表达式
 */
export const hexReg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;

/**
 * 验证是否为rgb颜色的正则表达式
 */
export const rgbReg = /^rgb\((\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5]),\s*(\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5]),\s*(\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5])\)$/;

/**
 * 验证是否为rgba颜色的正则表达式
 */
export const rgbaReg =
  /^rgba\((\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5]),\s*(\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5]),\s*(\d{1,2}|1\d{1,2}|2[0-4]\d|25[0-5]),\s*(0?\.\d|1(\.0)?)\)$/;

/**
 * 修改透明通道
 */
export function getAmendAlphaColor(color: string, alpha: number): string {
  const tinyColor: TinyColor = new TinyColor(color);
  return tinyColor.isValid ? tinyColor.setAlpha(alpha).toHexString() : color;
}

/**
 * 颜色是否为深色
 */
export function isDarkColor(color: string): boolean | undefined {
  const tinyColor: TinyColor = new TinyColor(color);
  return tinyColor.isValid ? tinyColor.isDark() : undefined;
}

/** 存储颜色 (isDarkColorStorage()专用) */
const isDarkColorStorageObj: Record<string, boolean | undefined> = {};

/**
 * 颜色是否为深色
 */
export function isDarkColorStorage(color: string): boolean | undefined {
  if (color in isDarkColorStorageObj) {
    return isDarkColorStorageObj[color]!;
  } else {
    const bool = isDarkColor(color);
    isDarkColorStorageObj[color] = bool;
    return bool;
  }
}

/**
 * 根据透明度计算更亮或者更暗颜色 (仅支持rgb 和 hex16,如不是则返回原颜色)
 * @param color - 颜色
 * @param percent - 百分比 0-100
 * @param type - 可选值 'dark' | 'light' | undefined，不传则根据颜色自动识别（如果是深色就得到更亮的颜色，如果是浅色就得到更暗的颜色），
 */
export function lightenDarkenColor(color: string, percent: number, type?: 'dark' | 'light' | null): string | undefined {
  const tinyColor: TinyColor = new TinyColor(color);
  if (tinyColor.isValid) {
    const baseCol = type === 'light' ? 255 : type === 'dark' ? 0 : isDarkColor(color) ? 0 : 255;
    const a = (tinyColor.getAlpha() || 1) * percent;
    tinyColor.r = Math.floor(a * tinyColor.r + (1 - a) * baseCol);
    tinyColor.g = Math.floor(a * tinyColor.g + (1 - a) * baseCol);
    tinyColor.b = Math.floor(a * tinyColor.b + (1 - a) * baseCol);
    const cor = tinyColor.toHexString();
    return cor;
  } else {
    return undefined;
  }
}
/** 存储颜色 (lightenDarkenColorStorage()专用) */
const lightenDarkenColorStorageObj: Record<string, Record<number, string | undefined>> = {};

/**
 * [带记忆功能版本] 根据透明度计算更亮或者更暗颜色 (仅支持rgb 和 hex16,如不是则返回原颜色)
 * @param color - 颜色
 * @param percent - 百分比 0-100
 * @param type - 可选值 'dark' | 'light' | undefined，不传则根据颜色自动识别（如果是深色就得到更亮的颜色，如果是浅色就得到更暗的颜色），
 */
export function lightenDarkenColorStorage(color: string, percent: number, type?: 'dark' | 'light' | null): string | undefined {
  if (color) {
    if (lightenDarkenColorStorageObj[color]?.[percent]) {
      return lightenDarkenColorStorageObj[color]?.[percent];
    } else {
      const col = lightenDarkenColor(color, percent, type);
      if (!lightenDarkenColorStorageObj[color] || typeof lightenDarkenColorStorageObj[color] !== 'object') {
        lightenDarkenColorStorageObj[color] = {};
      }
      lightenDarkenColorStorageObj[color][percent] = col;
      return col;
    }
  } else {
    return undefined;
  }
}

/**
 * 从某个颜色过度到某个颜色的中间颜色
 * @param initColor - 初始颜色(仅支持16进制颜色)
 * @param endColor - 需要过度到什么颜色(仅支持16进制颜色)
 */
export function useStepGradientColor(initColor: string, endColor: string) {
  // 将 hex 转换为rgb
  const sColor = new TinyColor(initColor)!;
  const eColor = new TinyColor(endColor)!;

  return {
    /**
     * 得到过度的颜色
     * @param step - 过度总步长
     * @param curr - 当前步长
     */
    getColor: (step: number, curr: number) => sColor.mix(eColor, (curr / step) * 100).toHexString(),
  };
}
